#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "codegen.h"
#include "tokens.h"

/*
 *  Código gerador
*/

void headGen(void){
      if (lexlevel == 0){
	printf("\t.section .text\n");
	printf("\t.global _start\n");
	printf("\t.type _start,@function\n");
        printf("_start:\n");
      }
      printf("\tenter $%d, $%d\n", 4*lexvarcount, lexlevel);
}

void footGen(void){
      printf("\tleave\n");
      if (lexlevel == 0){
	printf("\tmovl $1,%%eax\n");
	printf("\tmovl $0,%%ebx\n");
	printf("\tint $128\n");
      }else if (lexlevel > 0 /*&& (lexcategory == FUNCTION  || lexcategory == PROCEDURE)*/){
        printf("\tret\n");
      }
}

void ifGen(int lbl){
	printf("\tjz .L%d\n\t; if statement \n", lbl);
}

void elseGen(int lbl){
	printf("\tjmp .L%d\n.L%d: ; else statement\n  ", gLabel, lbl);
}

void endIfGen(int lbl){
	printf(".L%d:\n", lbl);
}

void beginWhileGen(int lbl_beg){
	printf(".L%d: ; while statement\n", lbl_beg);
}

void leaveWhileGen(int lbl_end){
	printf("\t jz .L%d\n", lbl_end);
}

void repeatWhileGen(int lbl_beg){
	printf("\t jmp .L%d\n", lbl_beg);
}

void endWhileGen(int lbl_end){
	printf(".L%d:\n", lbl_end);
}

void beginRepeatGen(int lbl_beg){
	printf("L%d: ; repeat statement\n", lbl_beg); 
}

void endRepeatGen(int lbl_beg, int lbl_end){
	printf("\t jz .L%d\n", lbl_end);
	printf("\t jmp .L%d\n", lbl_beg);
	printf("L%d:\n", lbl_end);
}

void beginForGen(int lbl_beg){
	printf("L%d: ; for statement\n", lbl_beg);
}

void leaveForGen(int lbl_end){
	printf("\t jz .L%d\n", lbl_end);
}

void endForGen(int lbl_beg, int lbl_end){
	printf("\t jmp .L%d\n", lbl_beg);
	printf("L%d:\n", lbl_end);
}

/*
 *  Adiciona EAX ao topo da pilha
*/

void addGen(void){
	printf("\taddl  %%eax, (%%esp)\n");
}

/*
 *  Subtrai EAX ao topo da pilha
*/

void subGen(void){
	printf("\tsubl  %%eax, (%%esp)\n");
} 

/*
 *  Multiplica EAX ao topo da pilha
*/

void mulGen(void){
	printf("\tmull (%%esp)\n");
}

/*
 *  Divide EAX pelo topo da pilha
*/

void divGen(void){
	printf("\tdivl (%%esp)\n");
} 

/*
 *  Atribuição de inteiros sem sinal pelo EAX
*/

void uIntGen(void){
	printf("\tmovl $%s, %%eax\n", lexeme);
	printf("\tpush %%eax\n");
}

/*
 *  Atribuição de ponto flutuante pelo EAX
*/

void floatGen(void){
	float value = strtod(lexeme,NULL);
	printf("\tmovl $0x%X, %%eax\n", *(unsigned int*)&value);
	printf("\tpush %%eax\n");
}

/*
 * Ações semânticas para Expressões
*/

void EGen(int *first, int oper){
	if(*first){
		printf("\tpushl %%eax\n");
		*first = 0;
	}

	if ( oper == '+'){
		addGen();
	}
	else{
		subGen();
	}

	if (lookahead != ADD) printf("\tpopl %%eax\n");
}

/*
 * Ações semânticas para Termos
*/

void TGen(int *first, int oper){
	if(*first){
		printf("\tpushl %%eax\n");
		*first = 0;
	}

	if ( oper == '*'){
		mulGen();
	}
	else{
		divGen();
	}

	if (lookahead != MUL) printf("\tpopl %%eax\n");
}
